package com.sixth.aspect;

import com.sixth.annotation.OperationLogAdvice;
import com.sixth.bean.MarketAdmin;
import com.sixth.bean.MarketLog;
import com.sixth.constant.Constant;
import com.sixth.mapper.MarketLogMapper;
import lombok.SneakyThrows;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @ClassName OpreationLogAspect
 * @Description TODO
 * @Author XiaoWJ
 * @Date 2022/9/8 19:35
 **/

@Aspect
@Component
public class OperationLogAspect {

    @Pointcut("@annotation(com.sixth.annotation.OperationLogAdvice)")
    public void operationLogPointcut() {
    }


    @Autowired
    MarketLogMapper marketLogMapper;

    @SneakyThrows
    @Around("operationLogPointcut()")
    public Object operationLog(ProceedingJoinPoint joinPoint) {
        // 获取request对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 获取客服端ip地址
        String ip = request.getRemoteAddr();
        // 获取委托类对象的字节码文件对象
        //Class<?> tClass = joinPoint.getTarget().getClass();
        // 获取正再执行的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        // 获得该方法上的注解
        OperationLogAdvice annotation = method.getAnnotation(OperationLogAdvice.class);

        // 获得注解中的操作类型和操作动作的值
        int operationType = annotation.operationType();
        String operation = annotation.operation();


        // 在logout方法执行之前获取操作人员的用户名
        String admin = null;

        // 当前方法不是登录方法
        if (!"login".equals(method.getName())) {
            PrincipalCollection principals =
                    SecurityUtils.getSubject().getPrincipals();

            MarketAdmin marketAdmin = (MarketAdmin) principals.getPrimaryPrincipal();
            admin = marketAdmin.getUsername();
        }
        // 执行委托类的方法
        Object proceed = joinPoint.proceed();

        // 从委托类方法返回的对象中获取操作状态
        Class<?> pClass = proceed.getClass();
        int code = 0;
        Field[] declaredFields = pClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            if ("errno".equals(declaredField.getName())) {
                code = (Integer) declaredField.get(proceed);
                break;
            }
        }

        boolean status = (code == 0) ? true : false;


        if ("login".equals(method.getName())) {
            if (code != 0) {
                admin = "匿名用户";
            } else {
                PrincipalCollection principals =
                        SecurityUtils.getSubject().getPrincipals();

                MarketAdmin marketAdmin = (MarketAdmin) principals.getPrimaryPrincipal();
                admin = marketAdmin.getUsername();
            }
        }
        // 将上述日志记录插入数据库中
        Date date = new Date();

        MarketLog marketLog = new MarketLog(null, admin, ip, operationType, operation, status, null, null, date, date, false);

        marketLogMapper.insertSelective(marketLog);

        return proceed;
    }
}
